From 8214bb953dee7f529747ce69ff81fe294259a6a0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Feb 2016 10:54:07 -0800 Subject: [PATCH] Implement source redirection This commit implements a scheme for .cargo/config files where sources can be redirected to other sources. The purpose of this will be to override crates.io for a few use cases: * Replace it with a mirror site that is sync'd to crates.io * Replace it with a "directory source" or some other local source This major feature of this redirection, however, is that none of it is encoded into the lock file. If one source is redirected to another then it is assumed that packages from both are exactly the same (e.g. `foo v0.0.1` is the same in both location). The lock file simply encodes the canonical soure (e.g. crates.io) rather than the replacement source. In the end this means that Cargo.lock files can be generated from any replacement source and shipped to other locations without the lockfile oscillating about where packages came from. Eventually this support will be extended to `Cargo.toml` itself (which will be encoded into the lock file), but that support is not implemented today. The syntax for what was implemented today looks like: # .cargo/config [source.my-awesome-registry] registry = 'https://example.com/path/to/index' [source.crates-io] replace-with = 'my-awesome-registry' Each source will have a canonical name and will be configured with the various keys underneath it (today just 'registry' and 'directory' will be accepted). The global `crates-io` source represents crates from the standard registry, and this can be replaced with other mirror sources. All tests have been modified to use this new infrastructure instead of the old `registry.index` configuration. This configuration is now also deprecated and will emit an unconditional warning about how it will no longer be used in the future. Finally, all subcommands now use this "source map" except for `cargo publish`, which will always publish to the default registry (in this case crates.io). --- src/bin/install.rs | 2 +- src/bin/login.rs | 2 +- src/cargo/core/package_id.rs | 4 +- src/cargo/core/registry.rs | 16 +- src/cargo/core/source.rs | 27 ++- src/cargo/ops/cargo_clean.rs | 2 +- src/cargo/ops/cargo_compile.rs | 15 +- src/cargo/ops/cargo_fetch.rs | 2 +- src/cargo/ops/cargo_generate_lockfile.rs | 4 +- src/cargo/ops/cargo_install.rs | 5 +- src/cargo/ops/cargo_package.rs | 8 +- src/cargo/ops/registry.rs | 11 +- src/cargo/sources/config.rs | 149 +++++++++++++++ src/cargo/sources/mod.rs | 6 +- src/cargo/sources/registry.rs | 17 +- src/cargo/sources/replaced.rs | 55 ++++++ src/cargo/util/config.rs | 31 +-- src/cargo/util/toml.rs | 2 +- tests/bad-config.rs | 233 ++++++++++++++++++++++- tests/build-script.rs | 4 +- tests/cargo_alias_config.rs | 2 +- tests/cargotest/support/registry.rs | 11 +- tests/install.rs | 18 +- tests/metadata.rs | 20 +- tests/overrides.rs | 18 +- tests/publish.rs | 42 ++-- tests/registry.rs | 89 ++++----- tests/search.rs | 10 +- tests/workspaces.rs | 6 +- 29 files changed, 639 insertions(+), 172 deletions(-) create mode 100644 src/cargo/sources/config.rs create mode 100644 src/cargo/sources/replaced.rs diff --git a/src/bin/install.rs b/src/bin/install.rs index e7d3d03f7..2a5868802 100644 --- a/src/bin/install.rs +++ b/src/bin/install.rs @@ -132,7 +132,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult> { } else if options.arg_crate == None { try!(SourceId::for_path(&config.cwd())) } else { - try!(SourceId::for_central(config)) + try!(SourceId::crates_io(config)) }; let krate = options.arg_crate.as_ref().map(|s| &s[..]); diff --git a/src/bin/login.rs b/src/bin/login.rs index 635321c57..a732c65fa 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -43,7 +43,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult> { let token = match options.arg_token.clone() { Some(token) => token, None => { - let src = try!(SourceId::for_central(config)); + let src = try!(SourceId::crates_io(config)); let mut src = RegistrySource::new(&src, config); try!(src.update()); let config = try!(src.config()); diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 7d24bbe0e..b29b8ca11 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -203,12 +203,12 @@ impl fmt::Debug for PackageId { mod tests { use super::PackageId; use core::source::SourceId; - use sources::RegistrySource; + use sources::CRATES_IO; use util::ToUrl; #[test] fn invalid_version_handled_nicely() { - let loc = RegistrySource::default_url().to_url().unwrap(); + let loc = CRATES_IO.to_url().unwrap(); let repo = SourceId::for_registry(&loc); assert!(PackageId::new("foo", "1.0", &repo).is_err()); diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 6dc2d9cc4..6e7d1bf8f 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -3,6 +3,7 @@ use std::collections::{HashSet, HashMap}; use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package}; use core::PackageSet; use util::{CargoResult, ChainError, Config, human, profile}; +use sources::config::SourceConfigMap; /// Source of information about a group of packages. /// @@ -47,7 +48,6 @@ impl<'a, T: ?Sized + Registry + 'a> Registry for Box { /// operations if necessary) and is ready to be queried for packages. pub struct PackageRegistry<'cfg> { sources: SourceMap<'cfg>, - config: &'cfg Config, // A list of sources which are considered "overrides" which take precedent // when querying for packages. @@ -71,6 +71,7 @@ pub struct PackageRegistry<'cfg> { source_ids: HashMap, locked: HashMap)>>>, + source_config: SourceConfigMap<'cfg>, } #[derive(PartialEq, Eq, Clone, Copy)] @@ -81,14 +82,15 @@ enum Kind { } impl<'cfg> PackageRegistry<'cfg> { - pub fn new(config: &'cfg Config) -> PackageRegistry<'cfg> { - PackageRegistry { + pub fn new(config: &'cfg Config) -> CargoResult> { + let source_config = try!(SourceConfigMap::new(config)); + Ok(PackageRegistry { sources: SourceMap::new(), source_ids: HashMap::new(), overrides: Vec::new(), - config: config, + source_config: source_config, locked: HashMap::new(), - } + }) } pub fn get(self, package_ids: &[PackageId]) -> PackageSet<'cfg> { @@ -164,8 +166,8 @@ impl<'cfg> PackageRegistry<'cfg> { fn load(&mut self, source_id: &SourceId, kind: Kind) -> CargoResult<()> { (|| { - // Save off the source - let source = source_id.load(self.config); + let source = try!(self.source_config.load(source_id)); + if kind == Kind::Override { self.overrides.push(source_id.clone()); } diff --git a/src/cargo/core/source.rs b/src/cargo/core/source.rs index e590f661b..2b5dc1347 100644 --- a/src/cargo/core/source.rs +++ b/src/cargo/core/source.rs @@ -4,13 +4,16 @@ use std::fmt::{self, Formatter}; use std::hash; use std::path::Path; use std::sync::Arc; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; +use std::sync::atomic::Ordering::SeqCst; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use url::Url; use core::{Package, PackageId, Registry}; -use sources::{PathSource, GitSource, RegistrySource}; +use ops; use sources::git; +use sources::{PathSource, GitSource, RegistrySource, CRATES_IO}; use util::{human, Config, CargoResult, ToUrl}; /// A Source finds and downloads remote packages based on names and @@ -185,8 +188,22 @@ impl SourceId { /// /// This is the main cargo registry by default, but it can be overridden in /// a `.cargo/config`. - pub fn for_central(config: &Config) -> CargoResult { - Ok(SourceId::for_registry(&try!(RegistrySource::url(config)))) + pub fn crates_io(config: &Config) -> CargoResult { + let cfg = try!(ops::registry_configuration(config)); + let url = if let Some(ref index) = cfg.index { + static WARNED: AtomicBool = ATOMIC_BOOL_INIT; + if !WARNED.swap(true, SeqCst) { + try!(config.shell().warn("custom registry support via \ + the `registry.index` configuration is \ + being removed, this functionality \ + will not work in the future")); + } + &index[..] + } else { + CRATES_IO + }; + let url = try!(url.to_url()); + Ok(SourceId::for_registry(&url)) } pub fn url(&self) -> &Url { @@ -247,7 +264,7 @@ impl SourceId { Kind::Registry => {} _ => return false, } - self.inner.url.to_string() == RegistrySource::default_url() + self.inner.url.to_string() == CRATES_IO } } diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 21cb053d1..e19b37f11 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -28,7 +28,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { return rm_rf(&target_dir); } - let mut registry = PackageRegistry::new(opts.config); + let mut registry = try!(PackageRegistry::new(opts.config)); let resolve = try!(ops::resolve_ws(&mut registry, ws)); let packages = ops::get_resolved_packages(&resolve, registry); diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 78d16365c..3ea700f49 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -97,7 +97,7 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>, no_default_features: bool) -> CargoResult<(PackageSet<'a>, Resolve)> { - let mut registry = PackageRegistry::new(ws.config()); + let mut registry = try!(PackageRegistry::new(ws.config())); if let Some(source) = source { registry.add_preloaded(try!(ws.current()).package_id().source_id(), @@ -389,6 +389,7 @@ fn add_overrides<'a>(registry: &mut PackageRegistry<'a>, None => return Ok(()) }; let current = try!(ws.current()); + let paths = paths.val.iter().map(|&(ref s, ref p)| { // The path listed next to the string is the config file in which the // key was located, so we want to pop off the `.cargo/config` component @@ -482,11 +483,11 @@ fn scrape_target_config(config: &Config, triple: &str) rerun_if_changed: Vec::new(), warnings: Vec::new(), }; - for (k, value) in try!(value.table()).0 { + for (k, value) in try!(value.table(&lib_name)).0 { let key = format!("{}.{}", key, k); match &k[..] { "rustc-flags" => { - let (flags, definition) = try!(value.string()); + let (flags, definition) = try!(value.string(&k)); let whence = format!("in `{}` (in {})", key, definition.display()); let (paths, links) = try!( @@ -496,22 +497,22 @@ fn scrape_target_config(config: &Config, triple: &str) output.library_links.extend(links); } "rustc-link-lib" => { - let list = try!(value.list()); + let list = try!(value.list(&k)); output.library_links.extend(list.iter() .map(|v| v.0.clone())); } "rustc-link-search" => { - let list = try!(value.list()); + let list = try!(value.list(&k)); output.library_paths.extend(list.iter().map(|v| { PathBuf::from(&v.0) })); } "rustc-cfg" => { - let list = try!(value.list()); + let list = try!(value.list(&k)); output.cfgs.extend(list.iter().map(|v| v.0.clone())); } _ => { - let val = try!(value.string()).0; + let val = try!(value.string(&k)).0; output.metadata.push((k.clone(), val.to_string())); } } diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 03b19ca5d..a0144c8f4 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -5,7 +5,7 @@ use util::CargoResult; /// Executes `cargo fetch`. pub fn fetch<'a>(ws: &Workspace<'a>) -> CargoResult<(Resolve, PackageSet<'a>)> { - let mut registry = PackageRegistry::new(ws.config()); + let mut registry = try!(PackageRegistry::new(ws.config())); let resolve = try!(ops::resolve_ws(&mut registry, ws)); let packages = get_resolved_packages(&resolve, registry); for id in resolve.iter() { diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index b196dec91..45ee2b101 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -16,7 +16,7 @@ pub struct UpdateOptions<'a> { } pub fn generate_lockfile(ws: &Workspace) -> CargoResult<()> { - let mut registry = PackageRegistry::new(ws.config()); + let mut registry = try!(PackageRegistry::new(ws.config())); let resolve = try!(ops::resolve_with_previous(&mut registry, ws, Method::Everything, None, None)); @@ -35,7 +35,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) Some(resolve) => resolve, None => return generate_lockfile(ws), }; - let mut registry = PackageRegistry::new(opts.config); + let mut registry = try!(PackageRegistry::new(opts.config)); let mut to_avoid = HashSet::new(); if opts.to_update.is_empty() { diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index b120ace95..d25bf11ba 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -13,7 +13,7 @@ use toml; use core::{SourceId, Source, Package, Dependency, PackageIdSpec}; use core::{PackageId, Workspace}; use ops::{self, CompileFilter}; -use sources::{GitSource, PathSource, RegistrySource}; +use sources::{GitSource, PathSource, SourceConfigMap}; use util::{CargoResult, ChainError, Config, human, internal}; use util::{Filesystem, FileLock}; @@ -54,6 +54,7 @@ pub fn install(root: Option<&str>, force: bool) -> CargoResult<()> { let config = opts.config; let root = try!(resolve_root(root, config)); + let map = try!(SourceConfigMap::new(config)); let (pkg, source) = if source_id.is_git() { try!(select_pkg(GitSource::new(source_id, config), source_id, krate, vers, &mut |git| git.read_packages())) @@ -70,7 +71,7 @@ pub fn install(root: Option<&str>, source_id, krate, vers, &mut |path| path.read_packages())) } else { - try!(select_pkg(RegistrySource::new(source_id, config), + try!(select_pkg(try!(map.load(source_id)), source_id, krate, vers, &mut |_| Err(human("must specify a crate to install from \ crates.io, or use --path or --git to \ diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 4e6ae0a9d..e6a89e331 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -247,21 +247,21 @@ fn run_verify(ws: &Workspace, tar: &File, opts: &PackageOpts) -> CargoResult<()> try!(archive.unpack(dst.parent().unwrap())); let manifest_path = dst.join("Cargo.toml"); - // When packages are uploaded to the registry, all path dependencies are - // implicitly converted to registry-based dependencies, so we rewrite those + // When packages are uploaded to a registry, all path dependencies are + // implicitly converted to registry dependencies, so we rewrite those // dependencies here. // // We also make sure to point all paths at `dst` instead of the previous // location that the package was originally read from. In locking the // `SourceId` we're telling it that the corresponding `PathSource` will be // considered updated and we won't actually read any packages. - let registry = try!(SourceId::for_central(config)); + let cratesio = try!(SourceId::crates_io(config)); let precise = Some("locked".to_string()); let new_src = try!(SourceId::for_path(&dst)).with_precise(precise); let new_pkgid = try!(PackageId::new(pkg.name(), pkg.version(), &new_src)); let new_summary = pkg.summary().clone().map_dependencies(|d| { if !d.source_id().is_path() { return d } - d.clone_inner().set_source_id(registry.clone()).into_dependency() + d.clone_inner().set_source_id(cratesio.clone()).into_dependency() }); let mut new_manifest = pkg.manifest().clone(); new_manifest.set_summary(new_summary.override_id(new_pkgid)); diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index e47b0f7a2..20ad7fcd9 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -163,16 +163,17 @@ pub fn registry(config: &Config, // Parse all configuration options let RegistryConfig { token: token_config, - index: index_config, + index: _index_config, } = try!(registry_configuration(config)); let token = token.or(token_config); - let index = index.or(index_config).unwrap_or(RegistrySource::default_url()); - let index = try!(index.to_url()); - let sid = SourceId::for_registry(&index); + let sid = match index { + Some(index) => SourceId::for_registry(&try!(index.to_url())), + None => try!(SourceId::crates_io(config)), + }; let api_host = { let mut src = RegistrySource::new(&sid, config); try!(src.update().chain_error(|| { - human(format!("failed to update registry {}", index)) + human(format!("failed to update {}", sid)) })); (try!(src.config())).api }; diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs new file mode 100644 index 000000000..b0e88f1eb --- /dev/null +++ b/src/cargo/sources/config.rs @@ -0,0 +1,149 @@ +//! Implementation of configuration for various sources +//! +//! This module will parse the various `source.*` TOML configuration keys into a +//! structure usable by Cargo itself. Currently this is primarily used to map +//! sources to one another via the `replace-with` key in `.cargo/config`. + +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +use url::Url; + +use core::{Source, SourceId}; +use sources::ReplacedSource; +use util::{CargoResult, Config, ChainError, human, ToUrl}; +use util::config::ConfigValue; + +pub struct SourceConfigMap<'cfg> { + cfgs: HashMap, + id2name: HashMap, + config: &'cfg Config, +} + +/// Configuration for a particular source, found in TOML looking like: +/// +/// ```toml +/// [source.crates-io] +/// registry = 'https://github.com/rust-lang/crates.io-index' +/// replace-with = 'foo' # optional +/// ``` +struct SourceConfig { + // id this source corresponds to, inferred from the various defined keys in + // the configuration + id: SourceId, + + // Name of the source that this source should be replaced with. This field + // is a tuple of (name, path) where path is where this configuration key was + // defined (the literal `.cargo/config` file). + replace_with: Option<(String, PathBuf)>, +} + +impl<'cfg> SourceConfigMap<'cfg> { + pub fn new(config: &'cfg Config) -> CargoResult> { + let mut base = try!(SourceConfigMap::empty(config)); + if let Some(table) = try!(config.get_table("source")) { + for (key, value) in table.val.iter() { + try!(base.add_config(key, value)); + } + } + Ok(base) + } + + pub fn empty(config: &'cfg Config) -> CargoResult> { + let mut base = SourceConfigMap { + cfgs: HashMap::new(), + id2name: HashMap::new(), + config: config, + }; + base.add("crates-io", SourceConfig { + id: try!(SourceId::crates_io(config)), + replace_with: None, + }); + Ok(base) + } + + pub fn load(&self, id: &SourceId) -> CargoResult> { + debug!("loading: {}", id); + let mut name = match self.id2name.get(id) { + Some(name) => name, + None => return Ok(id.load(self.config)), + }; + let mut path = Path::new("/"); + let orig_name = name; + loop { + let cfg = match self.cfgs.get(name) { + Some(cfg) => cfg, + None => bail!("could not find a configured source with the \ + name `{}` when attempting to lookup `{}` \ + (configuration in `{}`)", + name, orig_name, path.display()), + }; + match cfg.replace_with { + Some((ref s, ref p)) => { + name = s; + path = p; + } + None if *id == cfg.id => return Ok(id.load(self.config)), + None => { + let new_id = cfg.id.with_precise(id.precise() + .map(|s| s.to_string())); + let src = new_id.load(self.config); + return Ok(Box::new(ReplacedSource::new(id, &new_id, src))) + } + } + debug!("following pointer to {}", name); + if name == orig_name { + bail!("detected a cycle of `replace-with` sources, the source \ + `{}` is eventually replaced with itself \ + (configuration in `{}`)", name, path.display()) + } + } + } + + fn add(&mut self, name: &str, cfg: SourceConfig) { + self.id2name.insert(cfg.id.clone(), name.to_string()); + self.cfgs.insert(name.to_string(), cfg); + } + + fn add_config(&mut self, name: &str, cfg: &ConfigValue) -> CargoResult<()> { + let (table, _path) = try!(cfg.table(&format!("source.{}", name))); + let mut srcs = Vec::new(); + if let Some(val) = table.get("registry") { + let url = try!(url(val, &format!("source.{}.registry", name))); + srcs.push(SourceId::for_registry(&url)); + } + + let mut srcs = srcs.into_iter(); + let src = try!(srcs.next().chain_error(|| { + human(format!("no source URL specified for `source.{}`, needs \ + `registry` defined", name)) + })); + if srcs.next().is_some() { + return Err(human(format!("more than one source URL specified for \ + `source.{}`", name))) + } + + let mut replace_with = None; + if let Some(val) = table.get("replace-with") { + let (s, path) = try!(val.string(&format!("source.{}.replace-with", + name))); + replace_with = Some((s.to_string(), path.to_path_buf())); + } + + self.add(name, SourceConfig { + id: src, + replace_with: replace_with, + }); + + return Ok(()); + + fn url(cfg: &ConfigValue, key: &str) -> CargoResult { + let (url, path) = try!(cfg.string(key)); + url.to_url().chain_error(|| { + human(format!("configuration key `{}` specified an invalid \ + URL (in {})", key, path.display())) + + }) + } + } +} diff --git a/src/cargo/sources/mod.rs b/src/cargo/sources/mod.rs index 7db736193..53c573aa3 100644 --- a/src/cargo/sources/mod.rs +++ b/src/cargo/sources/mod.rs @@ -1,7 +1,11 @@ pub use self::path::PathSource; pub use self::git::GitSource; -pub use self::registry::RegistrySource; +pub use self::registry::{RegistrySource, CRATES_IO}; +pub use self::replaced::ReplacedSource; +pub use self::config::SourceConfigMap; pub mod path; pub mod git; pub mod registry; +pub mod config; +pub mod replaced; diff --git a/src/cargo/sources/registry.rs b/src/cargo/sources/registry.rs index 0b40e17c5..460285e41 100644 --- a/src/cargo/sources/registry.rs +++ b/src/cargo/sources/registry.rs @@ -180,8 +180,8 @@ use util::{hex, Sha256, paths, Filesystem, FileLock}; use util::network; use ops; -const DEFAULT: &'static str = "https://github.com/rust-lang/crates.io-index"; const INDEX_LOCK: &'static str = ".cargo-index-lock"; +pub static CRATES_IO: &'static str = "https://github.com/rust-lang/crates.io-index"; pub struct RegistrySource<'cfg> { source_id: SourceId, @@ -247,21 +247,6 @@ impl<'cfg> RegistrySource<'cfg> { } } - /// Get the configured default registry URL. - /// - /// This is the main cargo registry by default, but it can be overridden in - /// a .cargo/config - pub fn url(config: &Config) -> CargoResult { - let config = try!(ops::registry_configuration(config)); - let url = config.index.unwrap_or(DEFAULT.to_string()); - url.to_url() - } - - /// Get the default url for the registry - pub fn default_url() -> String { - DEFAULT.to_string() - } - /// Decode the configuration stored within the registry. /// /// This requires that the index has been at least checked out. diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs new file mode 100644 index 000000000..cd0ffd4b1 --- /dev/null +++ b/src/cargo/sources/replaced.rs @@ -0,0 +1,55 @@ +use core::{Source, Registry, PackageId, Package, Dependency, Summary, SourceId}; +use util::{CargoResult, ChainError, human}; + +pub struct ReplacedSource<'cfg> { + to_replace: SourceId, + replace_with: SourceId, + inner: Box, +} + +impl<'cfg> ReplacedSource<'cfg> { + pub fn new(to_replace: &SourceId, + replace_with: &SourceId, + src: Box) -> ReplacedSource<'cfg> { + ReplacedSource { + to_replace: to_replace.clone(), + replace_with: replace_with.clone(), + inner: src, + } + } +} + +impl<'cfg> Registry for ReplacedSource<'cfg> { + fn query(&mut self, dep: &Dependency) -> CargoResult> { + let dep = dep.clone().map_source(&self.to_replace, &self.replace_with); + let ret = try!(self.inner.query(&dep).chain_error(|| { + human(format!("failed to query replaced source `{}`", + self.to_replace)) + })); + Ok(ret.into_iter().map(|summary| { + summary.map_source(&self.replace_with, &self.to_replace) + }).collect()) + } +} + +impl<'cfg> Source for ReplacedSource<'cfg> { + fn update(&mut self) -> CargoResult<()> { + self.inner.update().chain_error(|| { + human(format!("failed to update replaced source `{}`", + self.to_replace)) + }) + } + + fn download(&mut self, id: &PackageId) -> CargoResult { + let id = id.with_source_id(&self.replace_with); + let pkg = try!(self.inner.download(&id).chain_error(|| { + human(format!("failed to download replaced source `{}`", + self.to_replace)) + })); + Ok(pkg.map_source(&self.replace_with, &self.to_replace)) + } + + fn fingerprint(&self, id: &Package) -> CargoResult { + self.inner.fingerprint(id) + } +} diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 28d890d76..43721f016 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -274,7 +274,7 @@ impl Config { } pub fn expected(&self, ty: &str, key: &str, val: CV) -> CargoResult { - val.expected(ty).map_err(|e| { + val.expected(ty, key).map_err(|e| { human(format!("invalid configuration for key `{}`\n{}", key, e)) }) } @@ -512,38 +512,39 @@ impl ConfigValue { Ok(()) } - pub fn i64(&self) -> CargoResult<(i64, &Path)> { + pub fn i64(&self, key: &str) -> CargoResult<(i64, &Path)> { match *self { CV::Integer(i, ref p) => Ok((i, p)), - _ => self.expected("integer"), + _ => self.expected("integer", key), } } - pub fn string(&self) -> CargoResult<(&str, &Path)> { + pub fn string(&self, key: &str) -> CargoResult<(&str, &Path)> { match *self { CV::String(ref s, ref p) => Ok((s, p)), - _ => self.expected("string"), + _ => self.expected("string", key), } } - pub fn table(&self) -> CargoResult<(&HashMap, &Path)> { + pub fn table(&self, key: &str) + -> CargoResult<(&HashMap, &Path)> { match *self { CV::Table(ref table, ref p) => Ok((table, p)), - _ => self.expected("table"), + _ => self.expected("table", key), } } - pub fn list(&self) -> CargoResult<&[(String, PathBuf)]> { + pub fn list(&self, key: &str) -> CargoResult<&[(String, PathBuf)]> { match *self { CV::List(ref list, _) => Ok(list), - _ => self.expected("list"), + _ => self.expected("list", key), } } - pub fn boolean(&self) -> CargoResult<(bool, &Path)> { + pub fn boolean(&self, key: &str) -> CargoResult<(bool, &Path)> { match *self { CV::Boolean(b, ref p) => Ok((b, p)), - _ => self.expected("bool"), + _ => self.expected("bool", key), } } @@ -567,10 +568,10 @@ impl ConfigValue { } } - fn expected(&self, wanted: &str) -> CargoResult { - Err(internal(format!("expected a {}, but found a {} in {}", - wanted, self.desc(), - self.definition_path().display()))) + fn expected(&self, wanted: &str, key: &str) -> CargoResult { + Err(human(format!("expected a {}, but found a {} for `{}` in {}", + wanted, self.desc(), key, + self.definition_path().display()))) } fn into_toml(self) -> toml::Value { diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index cdb3d999c..ffc089aa5 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -838,7 +838,7 @@ impl TomlDependency { cx.source_id.clone() } }, - (None, None) => try!(SourceId::for_central(cx.config)), + (None, None) => try!(SourceId::crates_io(cx.config)), }; let version = details.version.as_ref().map(|v| &v[..]); diff --git a/tests/bad-config.rs b/tests/bad-config.rs index 2ccece7d5..d7d0192bd 100644 --- a/tests/bad-config.rs +++ b/tests/bad-config.rs @@ -74,11 +74,12 @@ fn bad3() { proxy = true "#); Package::new("foo", "1.0.0").publish(); + assert_that(foo.cargo_process("publish").arg("-v"), execs().with_status(101).with_stderr("\ [UPDATING] registry `[..]` [ERROR] invalid configuration for key `http.proxy` -expected a string, but found a boolean in [..]config +expected a string, but found a boolean for `http.proxy` in [..]config ")); } @@ -95,7 +96,7 @@ fn bad4() { Caused by: invalid configuration for key `cargo-new.name` -expected a string, but found a boolean in [..]config +expected a string, but found a boolean for `cargo-new.name` in [..]config ")); } @@ -538,6 +539,156 @@ This will be considered an error in future versions ")); } +#[test] +fn bad_source_config1() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.foo] + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: no source URL specified for `source.foo`, needs [..] +")); +} + +#[test] +fn bad_source_config2() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = 'bar' + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: failed to load source for a dependency on `bar` + +Caused by: + Unable to update registry https://[..] + +Caused by: + could not find a configured source with the name `bar` \ + when attempting to lookup `crates-io` (configuration in [..]) +")); +} + +#[test] +fn bad_source_config3() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = 'crates-io' + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: failed to load source for a dependency on `bar` + +Caused by: + Unable to update registry https://[..] + +Caused by: + detected a cycle of `replace-with` sources, [..] +")); +} + +#[test] +fn bad_source_config4() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = 'bar' + + [source.bar] + registry = 'http://example.com' + replace-with = 'crates-io' + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: failed to load source for a dependency on `bar` + +Caused by: + Unable to update registry https://[..] + +Caused by: + detected a cycle of `replace-with` sources, the source `crates-io` is \ + eventually replaced with itself (configuration in [..]) +")); +} + +#[test] +fn bad_source_config5() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = 'bar' + + [source.bar] + registry = 'not a url' + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: configuration key `source.bar.registry` specified an invalid URL (in [..]) + +Caused by: + invalid url `not a url`: [..] +")); +} + #[test] fn both_git_and_path_specified() { let foo = project("foo") @@ -561,6 +712,31 @@ This will be considered an error in future versions ")); } +#[test] +fn bad_source_config6() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = ['not', 'a', 'string'] + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: expected a string, but found a array for `source.crates-io.replace-with` in [..] +")); +} + #[test] fn ignored_git_revision() { let foo = project("foo") @@ -581,3 +757,56 @@ fn ignored_git_revision() { [WARNING] key `branch` is ignored for dependency (bar). \ This will be considered an error in future versions")); } + +#[test] +#[ignore] +fn bad_source_config7() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.foo] + registry = 'http://example.com' + directory = 'file:///another/file' + "#); + + Package::new("bar", "0.1.0").publish(); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: more than one source URL specified for `source.foo` +")); +} + +#[test] +#[ignore] +fn bad_source_config8() { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies] + bar = "*" + "#) + .file("src/lib.rs", "") + .file(".cargo/config", r#" + [source.foo] + directory = 'file://another/file' + "#); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +error: failed to convert `file://another/file` to an absolute path (configured in [..]) +")); +} diff --git a/tests/build-script.rs b/tests/build-script.rs index 3cc250af3..7814a45a0 100644 --- a/tests/build-script.rs +++ b/tests/build-script.rs @@ -2113,7 +2113,7 @@ fn warnings_hidden_for_upstream() { .with_stderr("\ [UPDATING] registry `[..]` [DOWNLOADING] bar v0.1.0 ([..]) -[COMPILING] bar v0.1.0 ([..]) +[COMPILING] bar v0.1.0 [RUNNING] `rustc [..]` [RUNNING] `[..]` [RUNNING] `rustc [..]` @@ -2159,7 +2159,7 @@ fn warnings_printed_on_vv() { .with_stderr("\ [UPDATING] registry `[..]` [DOWNLOADING] bar v0.1.0 ([..]) -[COMPILING] bar v0.1.0 ([..]) +[COMPILING] bar v0.1.0 [RUNNING] `rustc [..]` [RUNNING] `[..]` warning: foo diff --git a/tests/cargo_alias_config.rs b/tests/cargo_alias_config.rs index c026382e4..b235d220f 100644 --- a/tests/cargo_alias_config.rs +++ b/tests/cargo_alias_config.rs @@ -19,7 +19,7 @@ fn alias_incorrect_config_type() { execs().with_status(101). with_stderr_contains("[ERROR] invalid configuration \ for key `alias.b-cargo-test` -expected a list, but found a integer in [..]")); +expected a list, but found a integer for [..]")); } diff --git a/tests/cargotest/support/registry.rs b/tests/cargotest/support/registry.rs index a783c6c0b..dcf6dc6d3 100644 --- a/tests/cargotest/support/registry.rs +++ b/tests/cargotest/support/registry.rs @@ -45,16 +45,23 @@ fn init() { } t!(t!(File::create(&config)).write_all(format!(r#" [registry] - index = "{reg}" token = "api-token" + + [source.crates-io] + registry = 'https://wut' + replace-with = 'dummy-registry' + + [source.dummy-registry] + registry = '{reg}' "#, reg = registry()).as_bytes())); // Init a new registry repo(®istry_path()) .file("config.json", &format!(r#" - {{"dl":"{}","api":""}} + {{"dl":"{0}","api":"{0}"}} "#, dl_url())) .build(); + fs::create_dir_all(dl_path().join("api/v1/crates")).unwrap(); } impl Package { diff --git a/tests/install.rs b/tests/install.rs index 8a967d1dc..52576d5bb 100644 --- a/tests/install.rs +++ b/tests/install.rs @@ -36,8 +36,8 @@ fn simple() { assert_that(cargo_process("install").arg("foo"), execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `[..]` -[DOWNLOADING] foo v0.0.1 (registry file://[..]) -[COMPILING] foo v0.0.1 (registry file://[..]) +[DOWNLOADING] foo v0.0.1 (registry [..]) +[COMPILING] foo v0.0.1 [FINISHED] release [optimized] target(s) in [..] [INSTALLING] {home}[..]bin[..]foo[..] warning: be sure to add `[..]` to your PATH to be able to run the installed binaries @@ -63,6 +63,8 @@ fn pick_max_version() { [UPDATING] registry `[..]` [DOWNLOADING] foo v0.0.2 (registry file://[..]) [COMPILING] foo v0.0.2 (registry file://[..]) +[DOWNLOADING] foo v0.0.2 (registry [..]) +[COMPILING] foo v0.0.2 [FINISHED] release [optimized] target(s) in [..] [INSTALLING] {home}[..]bin[..]foo[..] warning: be sure to add `[..]` to your PATH to be able to run the installed binaries @@ -77,7 +79,7 @@ fn missing() { assert_that(cargo_process("install").arg("bar"), execs().with_status(101).with_stderr("\ [UPDATING] registry [..] -[ERROR] could not find `bar` in `registry file://[..]` +[ERROR] could not find `bar` in `registry [..]` ")); } @@ -87,7 +89,7 @@ fn bad_version() { assert_that(cargo_process("install").arg("foo").arg("--vers=0.2.0"), execs().with_status(101).with_stderr("\ [UPDATING] registry [..] -[ERROR] could not find `foo` in `registry file://[..]` with version `0.2.0` +[ERROR] could not find `foo` in `registry [..]` with version `0.2.0` ")); } @@ -533,7 +535,7 @@ fn compile_failure() { assert_that(cargo_process("install").arg("--path").arg(p.root()), execs().with_status(101).with_stderr_contains("\ -[ERROR] failed to compile `foo v0.1.0 (file://[..])`, intermediate artifacts can be \ +[ERROR] failed to compile `foo v0.1.0 ([..])`, intermediate artifacts can be \ found at `[..]target` Caused by: @@ -583,9 +585,9 @@ fn list() { execs().with_status(0)); assert_that(cargo_process("install").arg("--list"), execs().with_status(0).with_stdout("\ -bar v0.2.1 (registry [..]): +bar v0.2.1: bar[..] -foo v0.0.1 (registry [..]): +foo v0.0.1: foo[..] ")); } @@ -606,7 +608,7 @@ fn uninstall_bin_does_not_exist() { execs().with_status(0)); assert_that(cargo_process("uninstall").arg("foo").arg("--bin=bar"), execs().with_status(101).with_stderr("\ -[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1 ([..])` +[ERROR] binary `bar[..]` not installed as part of `foo v0.0.1` ")); } diff --git a/tests/metadata.rs b/tests/metadata.rs index 478acf883..4d5df0f41 100644 --- a/tests/metadata.rs +++ b/tests/metadata.rs @@ -75,10 +75,10 @@ fn cargo_metadata_with_deps_and_version() { { "dependencies": [], "features": {}, - "id": "baz 0.0.1 (registry+file:[..])", + "id": "baz 0.0.1 (registry+[..])", "manifest_path": "[..]Cargo.toml", "name": "baz", - "source": "registry+file:[..]", + "source": "registry+[..]", "targets": [ { "kind": [ @@ -98,16 +98,16 @@ fn cargo_metadata_with_deps_and_version() { "name": "baz", "optional": false, "req": "^0.0.1", - "source": "registry+file:[..]", + "source": "registry+[..]", "target": null, "uses_default_features": true } ], "features": {}, - "id": "bar 0.0.1 (registry+file:[..])", + "id": "bar 0.0.1 (registry+[..])", "manifest_path": "[..]Cargo.toml", "name": "bar", - "source": "registry+file:[..]", + "source": "registry+[..]", "targets": [ { "kind": [ @@ -127,7 +127,7 @@ fn cargo_metadata_with_deps_and_version() { "name": "bar", "optional": false, "req": "*", - "source": "registry+file:[..]", + "source": "registry+[..]", "target": null, "uses_default_features": true } @@ -153,19 +153,19 @@ fn cargo_metadata_with_deps_and_version() { "nodes": [ { "dependencies": [ - "bar 0.0.1 (registry+file:[..])" + "bar 0.0.1 (registry+[..])" ], "id": "foo 0.5.0 (path+file:[..]foo)" }, { "dependencies": [ - "baz 0.0.1 (registry+file:[..])" + "baz 0.0.1 (registry+[..])" ], - "id": "bar 0.0.1 (registry+file:[..])" + "id": "bar 0.0.1 (registry+[..])" }, { "dependencies": [], - "id": "baz 0.0.1 (registry+file:[..])" + "id": "baz 0.0.1 (registry+[..])" } ], "root": "foo 0.5.0 (path+file:[..]foo)" diff --git a/tests/overrides.rs b/tests/overrides.rs index a0341ca7d..5eebed0bf 100644 --- a/tests/overrides.rs +++ b/tests/overrides.rs @@ -3,7 +3,7 @@ extern crate hamcrest; use cargotest::support::git; use cargotest::support::paths; -use cargotest::support::registry::{registry, Package}; +use cargotest::support::registry::Package; use cargotest::support::{execs, project}; use hamcrest::assert_that; @@ -145,7 +145,7 @@ fn transitive() { [UPDATING] git repository `[..]` [DOWNLOADING] bar v0.2.0 (registry [..]) [COMPILING] foo v0.1.0 (file://[..]) -[COMPILING] bar v0.2.0 (registry [..]) +[COMPILING] bar v0.2.0 [COMPILING] local v0.0.1 (file://[..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] ")); @@ -343,7 +343,7 @@ fn override_adds_some_deps() { [UPDATING] registry `file://[..]` [UPDATING] git repository `[..]` [DOWNLOADING] foo v0.1.1 (registry [..]) -[COMPILING] foo v0.1.1 (registry [..]) +[COMPILING] foo v0.1.1 [COMPILING] bar v0.1.0 ([..]) [COMPILING] local v0.0.1 (file://[..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] @@ -356,7 +356,9 @@ fn override_adds_some_deps() { execs().with_status(0).with_stderr("\ [UPDATING] git repository `file://[..]` ")); - assert_that(p.cargo("update").arg("-p").arg(&format!("{}#bar", registry())), + assert_that(p.cargo("update") + .arg("-p") + .arg("https://github.com/rust-lang/crates.io-index#bar"), execs().with_status(0).with_stderr("\ [UPDATING] registry `file://[..]` ")); @@ -532,8 +534,10 @@ fn multiple_specs() { [replace] "foo:0.1.0" = {{ git = '{0}' }} - "{1}#foo:0.1.0" = {{ git = '{0}' }} - "#, foo.url(), registry())) + + [replace."https://github.com/rust-lang/crates.io-index#foo:0.1.0"] + git = '{0}' + "#, foo.url())) .file("src/lib.rs", ""); assert_that(p.cargo_process("build"), @@ -545,7 +549,7 @@ error: overlapping replacement specifications found: * [..] * [..] -both specifications match: foo v0.1.0 ([..]) +both specifications match: foo v0.1.0 ")); } diff --git a/tests/publish.rs b/tests/publish.rs index ad02f97f1..6b7b19bb0 100644 --- a/tests/publish.rs +++ b/tests/publish.rs @@ -25,13 +25,12 @@ fn upload() -> Url { Url::from_file_path(&*upload_path()).ok().unwrap() } fn setup() { let config = paths::root().join(".cargo/config"); - fs::create_dir_all(config.parent().unwrap()).unwrap(); - File::create(&config).unwrap().write_all(&format!(r#" + t!(fs::create_dir_all(config.parent().unwrap())); + t!(t!(File::create(&config)).write_all(&format!(r#" [registry] - index = "{reg}" token = "api-token" - "#, reg = registry()).as_bytes()).unwrap(); - fs::create_dir_all(&upload_path().join("api/v1/crates")).unwrap(); + "#).as_bytes())); + t!(fs::create_dir_all(&upload_path().join("api/v1/crates"))); repo(®istry_path()) .file("config.json", &format!(r#"{{ @@ -56,7 +55,8 @@ fn simple() { "#) .file("src/main.rs", "fn main() {}"); - assert_that(p.cargo_process("publish").arg("--no-verify"), + assert_that(p.cargo_process("publish").arg("--no-verify") + .arg("--host").arg(registry().to_string()), execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `{reg}` [WARNING] manifest has no documentation, [..] @@ -110,7 +110,8 @@ fn git_deps() { "#) .file("src/main.rs", "fn main() {}"); - assert_that(p.cargo_process("publish").arg("-v").arg("--no-verify"), + assert_that(p.cargo_process("publish").arg("-v").arg("--no-verify") + .arg("--host").arg(registry().to_string()), execs().with_status(101).with_stderr("\ [UPDATING] registry [..] [ERROR] all dependencies must come from the same source. @@ -143,7 +144,8 @@ fn path_dependency_no_version() { "#) .file("bar/src/lib.rs", ""); - assert_that(p.cargo_process("publish"), + assert_that(p.cargo_process("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(101).with_stderr("\ [UPDATING] registry [..] [ERROR] all path dependencies must have a version specified when publishing. @@ -167,7 +169,8 @@ fn unpublishable_crate() { "#) .file("src/main.rs", "fn main() {}"); - assert_that(p.cargo_process("publish"), + assert_that(p.cargo_process("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(101).with_stderr("\ [ERROR] some crates cannot be published. `foo` is marked as unpublishable @@ -195,7 +198,8 @@ fn dont_publish_dirty() { let p = project("foo"); t!(File::create(p.root().join("bar"))); - assert_that(p.cargo("publish"), + assert_that(p.cargo("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(101).with_stderr("\ [UPDATING] registry `[..]` error: 1 dirty files found in the working directory: @@ -226,7 +230,8 @@ fn publish_clean() { .build(); let p = project("foo"); - assert_that(p.cargo("publish"), + assert_that(p.cargo("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(0)); } @@ -251,7 +256,8 @@ fn publish_in_sub_repo() { let p = project("foo"); t!(File::create(p.root().join("baz"))); - assert_that(p.cargo("publish").cwd(p.root().join("bar")), + assert_that(p.cargo("publish").cwd(p.root().join("bar")) + .arg("--host").arg(registry().to_string()), execs().with_status(0)); } @@ -277,7 +283,8 @@ fn publish_when_ignored() { let p = project("foo"); t!(File::create(p.root().join("baz"))); - assert_that(p.cargo("publish"), + assert_that(p.cargo("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(0)); } @@ -301,7 +308,8 @@ fn ignore_when_crate_ignored() { .nocommit_file("bar/src/main.rs", "fn main() {}"); let p = project("foo"); t!(File::create(p.root().join("bar/baz"))); - assert_that(p.cargo("publish").cwd(p.root().join("bar")), + assert_that(p.cargo("publish").cwd(p.root().join("bar")) + .arg("--host").arg(registry().to_string()), execs().with_status(0)); } @@ -324,7 +332,8 @@ fn new_crate_rejected() { .nocommit_file("src/main.rs", "fn main() {}"); let p = project("foo"); t!(File::create(p.root().join("baz"))); - assert_that(p.cargo("publish"), + assert_that(p.cargo("publish") + .arg("--host").arg(registry().to_string()), execs().with_status(101)); } @@ -343,7 +352,8 @@ fn dry_run() { "#) .file("src/main.rs", "fn main() {}"); - assert_that(p.cargo_process("publish").arg("--dry-run"), + assert_that(p.cargo_process("publish").arg("--dry-run") + .arg("--host").arg(registry().to_string()), execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `{reg}` [WARNING] manifest has no documentation, [..] diff --git a/tests/registry.rs b/tests/registry.rs index 93d61ea6d..60ffdae75 100644 --- a/tests/registry.rs +++ b/tests/registry.rs @@ -32,7 +32,7 @@ fn simple() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `{reg}` [DOWNLOADING] bar v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -43,8 +43,8 @@ fn simple() { assert_that(p.cargo_process("build"), execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `{reg}` -[..] bar v0.0.1 (registry file://[..]) -[..] foo v0.0.1 ({dir}) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", dir = p.url(), @@ -73,8 +73,8 @@ fn deps() { [UPDATING] registry `{reg}` [DOWNLOADING] [..] v0.0.1 (registry file://[..]) [DOWNLOADING] [..] v0.0.1 (registry file://[..]) -[COMPILING] baz v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] baz v0.0.1 +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -102,7 +102,7 @@ fn nonexistent() { execs().with_status(101).with_stderr("\ [UPDATING] registry [..] [ERROR] no matching package named `nonexistent` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: >= 0.0.0 ")); } @@ -127,7 +127,7 @@ fn wrong_version() { assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr_contains("\ [ERROR] no matching package named `foo` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: >= 1.0.0 versions found: 0.0.2, 0.0.1 ")); @@ -138,7 +138,7 @@ versions found: 0.0.2, 0.0.1 assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr_contains("\ [ERROR] no matching package named `foo` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: >= 1.0.0 versions found: 0.0.4, 0.0.3, 0.0.2, ... ")); @@ -168,6 +168,9 @@ fn bad_cksum() { [DOWNLOADING] bad-cksum [..] [ERROR] unable to get packages from source +Caused by: + failed to download replaced source `registry https://[..]` + Caused by: failed to download package `bad-cksum v0.0.1 (registry file://[..])` from [..] @@ -195,7 +198,7 @@ fn update_registry() { assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr_contains("\ [ERROR] no matching package named `notyet` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: >= 0.0.0 ")); @@ -205,7 +208,7 @@ version required: >= 0.0.0 execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `{reg}` [DOWNLOADING] notyet v0.0.1 (registry file://[..]) -[COMPILING] notyet v0.0.1 (registry file://[..]) +[COMPILING] notyet v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -247,7 +250,7 @@ fn package_with_path_deps() { Caused by: no matching package named `notyet` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: ^0.0.1 ")); @@ -259,7 +262,7 @@ version required: ^0.0.1 [VERIFYING] foo v0.0.1 ({dir}) [UPDATING] registry `[..]` [DOWNLOADING] notyet v0.0.1 (registry file://[..]) -[COMPILING] notyet v0.0.1 (registry file://[..]) +[COMPILING] notyet v0.0.1 [COMPILING] foo v0.0.1 ({dir}[..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", dir = p.url()))); @@ -286,7 +289,7 @@ fn lockfile_locks() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `[..]` [DOWNLOADING] bar v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -322,8 +325,8 @@ fn lockfile_locks_transitively() { [UPDATING] registry `[..]` [DOWNLOADING] [..] v0.0.1 (registry file://[..]) [DOWNLOADING] [..] v0.0.1 (registry file://[..]) -[COMPILING] baz v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] baz v0.0.1 +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -362,8 +365,8 @@ fn yanks_are_not_used() { [UPDATING] registry `[..]` [DOWNLOADING] [..] v0.0.1 (registry file://[..]) [DOWNLOADING] [..] v0.0.1 (registry file://[..]) -[COMPILING] baz v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] baz v0.0.1 +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -392,7 +395,7 @@ fn relying_on_a_yank_is_bad() { assert_that(p.cargo("build"), execs().with_status(101).with_stderr_contains("\ [ERROR] no matching package named `baz` found (required by `bar`) -location searched: registry file://[..] +location searched: registry [..] version required: = 0.0.2 versions found: 0.0.1 ")); @@ -428,7 +431,7 @@ fn yanks_in_lockfiles_are_ok() { assert_that(p.cargo("update"), execs().with_status(101).with_stderr_contains("\ [ERROR] no matching package named `bar` found (required by `foo`) -location searched: registry file://[..] +location searched: registry [..] version required: * ")); } @@ -490,14 +493,14 @@ fn update_lockfile() { .arg("-p").arg("bar").arg("--precise").arg("0.0.2"), execs().with_status(0).with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] bar v0.0.1 (registry file://[..]) -> v0.0.2 +[UPDATING] bar v0.0.1 -> v0.0.2 ")); println!("0.0.2 build"); assert_that(p.cargo("build"), execs().with_status(0).with_stderr(&format!("\ [DOWNLOADING] [..] v0.0.2 (registry file://[..]) -[COMPILING] bar v0.0.2 (registry file://[..]) +[COMPILING] bar v0.0.2 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -508,14 +511,14 @@ fn update_lockfile() { .arg("-p").arg("bar"), execs().with_status(0).with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] bar v0.0.2 (registry file://[..]) -> v0.0.3 +[UPDATING] bar v0.0.2 -> v0.0.3 ")); println!("0.0.3 build"); assert_that(p.cargo("build"), execs().with_status(0).with_stderr(&format!("\ [DOWNLOADING] [..] v0.0.3 (registry file://[..]) -[COMPILING] bar v0.0.3 (registry file://[..]) +[COMPILING] bar v0.0.3 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -528,8 +531,8 @@ fn update_lockfile() { .arg("-p").arg("bar"), execs().with_status(0).with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] bar v0.0.3 (registry file://[..]) -> v0.0.4 -[ADDING] spam v0.2.5 (registry file://[..]) +[UPDATING] bar v0.0.3 -> v0.0.4 +[ADDING] spam v0.2.5 ")); println!("new dependencies update"); @@ -538,8 +541,8 @@ fn update_lockfile() { .arg("-p").arg("bar"), execs().with_status(0).with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] bar v0.0.4 (registry file://[..]) -> v0.0.5 -[REMOVING] spam v0.2.5 (registry file://[..]) +[UPDATING] bar v0.0.4 -> v0.0.5 +[REMOVING] spam v0.2.5 ")); } @@ -565,7 +568,7 @@ fn dev_dependency_not_used() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `[..]` [DOWNLOADING] [..] v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -633,7 +636,7 @@ fn updating_a_dep() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `[..]` [DOWNLOADING] bar v0.0.1 (registry file://[..]) -[COMPILING] bar v0.0.1 (registry file://[..]) +[COMPILING] bar v0.0.1 [COMPILING] a v0.0.1 ({dir}/a) [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs @@ -656,7 +659,7 @@ fn updating_a_dep() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] registry `[..]` [DOWNLOADING] bar v0.1.0 (registry file://[..]) -[COMPILING] bar v0.1.0 (registry file://[..]) +[COMPILING] bar v0.1.0 [COMPILING] a v0.0.1 ({dir}/a) [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs @@ -702,7 +705,7 @@ fn git_and_registry_dep() { [UPDATING] [..] [UPDATING] [..] [DOWNLOADING] a v0.0.1 (registry file://[..]) -[COMPILING] a v0.0.1 (registry [..]) +[COMPILING] a v0.0.1 [COMPILING] b v0.0.1 ([..]) [COMPILING] foo v0.0.1 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs @@ -729,9 +732,7 @@ fn update_publish_then_update() { "#) .file("src/main.rs", "fn main() {}"); p.build(); - Package::new("a", "0.1.0").publish(); - assert_that(p.cargo("build"), execs().with_status(0)); @@ -749,7 +750,7 @@ fn update_publish_then_update() { execs().with_status(0).with_stderr(&format!("\ [UPDATING] [..] [DOWNLOADING] a v0.1.1 (registry file://[..]) -[COMPILING] a v0.1.1 (registry [..]) +[COMPILING] a v0.1.1 [COMPILING] foo v0.5.0 ({dir}) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ", @@ -809,15 +810,15 @@ fn update_transitive_dependency() { execs().with_status(0) .with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] b v0.1.0 (registry [..]) -> v0.1.1 +[UPDATING] b v0.1.0 -> v0.1.1 ")); assert_that(p.cargo("build"), execs().with_status(0) .with_stderr("\ [DOWNLOADING] b v0.1.1 (registry file://[..]) -[COMPILING] b v0.1.1 (registry [..]) -[COMPILING] a v0.1.0 (registry [..]) +[COMPILING] b v0.1.1 +[COMPILING] a v0.1.0 [COMPILING] foo v0.5.0 ([..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ")); @@ -892,15 +893,15 @@ fn update_multiple_packages() { execs().with_status(0) .with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] a v0.1.0 (registry [..]) -> v0.1.1 -[UPDATING] b v0.1.0 (registry [..]) -> v0.1.1 +[UPDATING] a v0.1.0 -> v0.1.1 +[UPDATING] b v0.1.0 -> v0.1.1 ")); assert_that(p.cargo("update").arg("-pb").arg("-pc"), execs().with_status(0) .with_stderr("\ [UPDATING] registry `[..]` -[UPDATING] c v0.1.0 (registry [..]) -> v0.1.1 +[UPDATING] c v0.1.0 -> v0.1.1 ")); assert_that(p.cargo("build"), @@ -912,11 +913,11 @@ fn update_multiple_packages() { .with_stderr_contains("\ [DOWNLOADING] c v0.1.1 (registry file://[..])") .with_stderr_contains("\ -[COMPILING] a v0.1.1 (registry [..])") +[COMPILING] a v0.1.1") .with_stderr_contains("\ -[COMPILING] b v0.1.1 (registry [..])") +[COMPILING] b v0.1.1") .with_stderr_contains("\ -[COMPILING] c v0.1.1 (registry [..])") +[COMPILING] c v0.1.1") .with_stderr_contains("\ [COMPILING] foo v0.5.0 ([..])")); } @@ -1034,7 +1035,7 @@ fn only_download_relevant() { execs().with_status(0).with_stderr("\ [UPDATING] registry `[..]` [DOWNLOADING] baz v0.1.0 ([..]) -[COMPILING] baz v0.1.0 ([..]) +[COMPILING] baz v0.1.0 [COMPILING] bar v0.5.0 ([..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] secs ")); diff --git a/tests/search.rs b/tests/search.rs index 19f04a33b..b2f1c8ad1 100644 --- a/tests/search.rs +++ b/tests/search.rs @@ -22,10 +22,6 @@ fn api() -> Url { Url::from_file_path(&*api_path()).ok().unwrap() } fn setup() { let config = paths::root().join(".cargo/config"); fs::create_dir_all(config.parent().unwrap()).unwrap(); - File::create(&config).unwrap().write_all(format!(r#" - [registry] - index = "{reg}" - "#, reg = registry()).as_bytes()).unwrap(); fs::create_dir_all(&api_path().join("api/v1")).unwrap(); repo(®istry_path()) @@ -85,7 +81,8 @@ fn simple() { .write_all(contents.as_bytes()).unwrap(); } - assert_that(cargo_process("search").arg("postgres"), + assert_that(cargo_process("search").arg("postgres") + .arg("--host").arg(registry().to_string()), execs().with_status(0) .with_stderr("\ [UPDATING] registry `[..]`") @@ -136,7 +133,8 @@ fn multiple_query_params() { .write_all(contents.as_bytes()).unwrap(); } - assert_that(cargo_process("search").arg("postgres").arg("sql"), + assert_that(cargo_process("search").arg("postgres").arg("sql") + .arg("--host").arg(registry().to_string()), execs().with_status(0) .with_stderr("\ [UPDATING] registry `[..]`") diff --git a/tests/workspaces.rs b/tests/workspaces.rs index dcec77ae3..8ded09b77 100644 --- a/tests/workspaces.rs +++ b/tests/workspaces.rs @@ -502,7 +502,7 @@ fn share_dependencies() { .with_stderr("\ [UPDATING] registry `[..]` [DOWNLOADING] dep1 v0.1.3 ([..]) -[COMPILING] dep1 v0.1.3 ([..]) +[COMPILING] dep1 v0.1.3 [COMPILING] foo v0.1.0 ([..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] ")); @@ -587,7 +587,7 @@ fn lock_works_for_everyone() { execs().with_status(0) .with_stderr("\ [DOWNLOADING] dep2 v0.1.0 ([..]) -[COMPILING] dep2 v0.1.0 ([..]) +[COMPILING] dep2 v0.1.0 [COMPILING] foo v0.1.0 ([..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] ")); @@ -596,7 +596,7 @@ fn lock_works_for_everyone() { execs().with_status(0) .with_stderr("\ [DOWNLOADING] dep1 v0.1.0 ([..]) -[COMPILING] dep1 v0.1.0 ([..]) +[COMPILING] dep1 v0.1.0 [COMPILING] bar v0.1.0 ([..]) [FINISHED] debug [unoptimized + debuginfo] target(s) in [..] ")); -- 2.30.2